package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.utils.ObjectUtil;
import com.zzyl.utils.StringUtils;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeviceServiceImp implements DeviceService {
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private Client client;
    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    /**
     * 同步数据
     */
    @Override
    public void syncProductList() {
        //定义请求参数
        QueryProductListRequest request = new QueryProductListRequest();
        request.setPageSize(200);
        request.setCurrentPage(1);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        // 获取响应结果
        QueryProductListResponse response;
        try {
            response = client.queryProductList(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //判断是否调用成功
        if (!response.getBody().getSuccess()) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //获取响应的数据
        List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo
                = response.getBody().getData().getList().getProductInfo();
        List<ProductVo> productVoList = BeanUtil.copyToList(productInfo, ProductVo.class);
        // 存入redis
        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY,JSONUtil.toJsonStr(productVoList));
    }

        @Override
    public List<ProductVo> allProduct() {
            //从缓存中获取数据
            String jsonString = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);
            //如果为空，返回空集合
            if (ObjectUtil.isEmpty(jsonString)){
                return Collections.emptyList();
            }
            //不为空，则返回数据
            List<ProductVo> productVos = JSONUtil.toList(jsonString, ProductVo.class);
            return productVos;
        }

    /**
     * 注册设备
     * @param deviceDto
     */
    @Override
    public ResponseResult registerDevice(DeviceDto deviceDto) {
        //检验设备名称是否重复
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if(count > 0){
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        //iot新增设备
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        RegisterDeviceResponse response = null;
        try {
            response = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        //接口是否调通
        if(response == null || !response.getBody().success){
            throw new RuntimeException(response.getBody().getErrorMessage());
        }

        //属性拷贝
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(response.getBody().getData().getIotId());
        //产品名称
        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductRequest.setProductKey(deviceDto.getProductKey());
        QueryProductResponse queryProductResponse;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
        //设置产品名称
        if(queryProductResponse.getBody().success){
            device.setProductName(queryProductResponse.getBody().getData().productName);
        }
        //如果设备绑定的位置是随身设备，则把物理绑定位置设置为-1
        //原因是为了后期方便通过位置字段查询老人数据
        if(device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        device.setHaveEntranceGuard(0);
        //保存设备
        try {
            deviceMapper.insertSelective(device);
        } catch (Exception e) {

            //删除iot中的设备数据
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setDeviceName(device.getDeviceName());
            deleteDeviceRequest.setIotId(device.getIotId());
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setProductKey(device.getProductKey());

            try {
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
            throw new BaseException(BasicEnum.RE_SELECT_PRODUCT);
        }
        return ResponseResult.success();
    }

    /**
     * 分页查询
     * @param devicePageQueryDto
     * @return
     */
    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {
        PageHelper.startPage(devicePageQueryDto.getPageNum(),devicePageQueryDto.getPageSize());
        Page<DeviceVo> deviceVos = deviceMapper.selectByPage(devicePageQueryDto);
        return PageResponse.of(deviceVos,DeviceVo.class);
    }

    /**
     * 查询设备详细数据
     *
     * @param request 查询设备详细请求模型
     * @return
     */
    @Override
    public ResponseResult queryDeviceDetail(QueryDeviceDetailRequest request) {
        // 请求参数还差一个实例id，给请求对象设置实例id。
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //通过客户端查询，并返回对象。
        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //判断接口是否调通
        if (!response.getBody().getSuccess()){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        //查询数据库的数据
        DeviceVo deviceVo = deviceMapper.selectByIotId(response.getBody().getData().getIotId());

        //得到iot的数据
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        //合并数据
        BeanUtil.copyProperties(data,deviceVo,CopyOptions.create().ignoreNullValue());
        return ResponseResult.success(deviceVo);
    }

    /**
     * 查询指定设备的物模型运行状态
     * @param request
     * @return
     */
    @Override
    public ResponseResult queryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDevicePropertyStatusResponse response;

        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = response.getBody().getData();
        return ResponseResult.success(data);
    }

    @Override
    public ResponseResult queryThingModePublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryThingModelPublishedResponse response;

        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        return ResponseResult.success(response.getBody().getData());
    }

    /**
     * 修改设备备注
     * @param deviceDto
     */
    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //获取请求参数
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        List<BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> list =new ArrayList<>();

        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo deviceNicknameRequestDeviceNicknameInfo
                = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        list.add(deviceNicknameRequestDeviceNicknameInfo);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setDeviceNicknameInfo(list);
        //获取响应结果
        BatchUpdateDeviceNicknameResponse response;

        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        //判断是否调用成功
        if (!response.getBody().getSuccess()){
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        // 修改数据库数据
        try {
            deviceMapper.updateDevice(device);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
    }

    /**
     * 删除设备
     * @param deviceDto
     */
    @Override
    public void deleteDevice(DeviceDto deviceDto) {
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        BeanUtil.copyProperties(deviceDto,request);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        log.info("=================== {}",request);
        DeleteDeviceResponse response;
        try {
            response = client.deleteDevice(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        if (response == null || !response.getBody().getSuccess()){
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        try {
            deviceMapper.deleteDevice(device);
        } catch (Exception e) {
            throw new RuntimeException("设备删除失败");
        }
    }
}


